﻿#include "mycustomplot.h"
#include "qcustomplot.h"

#include <QRubberBand>

MyCustomPlot::MyCustomPlot(QWidget *parent) :
    QCustomPlot(parent),
    chromeGraph(nullptr),
    voltGraph(nullptr),
    rbCancel(true)
{
    rbRect = new QRubberBand(QRubberBand::Rectangle, this);
}

MyCustomPlot::~MyCustomPlot()
{

}

void MyCustomPlot::init()
{
    //每条曲线都会独占一个graph()
    chromeGraph = this->addGraph();
    chromeGraph->setPen(QPen(Qt::red)); // 曲线的颜色
    //chromeGraph->setBrush(QBrush(QColor(0, 0, 255, 20))); // 曲线与X轴包围区的颜色

    voltGraph = this->addGraph();//添加graph等价于添加新曲线
    //this->graph(1)->setPen(QPen(Qt::red)); // 曲线的颜色
    voltGraph->setPen(QPen(Qt::green));

    fireGraph[0] = this->addGraph();
    fireGraph[0]->setPen(QPen(Qt::red));
    fireGraph[1] = this->addGraph();
    fireGraph[1]->setPen(QPen(Qt::green));
    fireGraph[2] = this->addGraph();
    fireGraph[2]->setPen(QPen(Qt::blue));

    // 边框右侧和上侧均显示刻度线，但不显示刻度值:
    // (参见 QCPAxisRect::setupFullAxesBox for a quicker method to do this)
    this->xAxis2->setVisible(true);
    this->xAxis2->setTickLabels(false);
    this->yAxis2->setVisible(true);
    this->yAxis2->setTickLabels(false);
    // 使上下两个X轴的范围总是相等，使左右两个Y轴的范围总是相等
    connect(this->xAxis, SIGNAL(rangeChanged(QCPRange)), this->xAxis2, SLOT(setRange(QCPRange)));
    connect(this->yAxis, SIGNAL(rangeChanged(QCPRange)), this->yAxis2, SLOT(setRange(QCPRange)));

    //自动调整XY轴的范围，以便显示出graph(0)中所有的点
    chromeGraph->rescaleAxes();
    //自动调整XY轴的范围，以便显示出graph(1)中所有的点
    voltGraph->rescaleAxes(true);
    // 支持鼠标拖拽轴的范围、滚动缩放轴的范围，左键点选图层（每条曲线独占一个图层）
    this->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
}

void MyCustomPlot::clear()
{
    QVector<double> x, y0, y1;

    chromeGraph->setData(x, y0);
    voltGraph->setData(x, y1);

    this->replot();
}

void MyCustomPlot::demoTest()
{
    // 生成模拟数据点 (x-y0 第一条曲线, x-y1为第2条曲线):
    QVector<double> x(251), y0(251), y1(251);
    for (int i=0; i<251; ++i)
    {
        x[i] = i;
        y0[i] = qExp(-i/150.0)*qCos(i/10.0); // 第一条曲线：y0衰减cos
        y1[i] = qExp(-i/150.0);              // 第二条曲线：y1衰减指数
    }
    // 把已存在的数据填充进graph的数据区
    chromeGraph->setData(x, y0);
    voltGraph->setData(x, y1);
    // 立即刷新图像
    showAllGraph();
}

void MyCustomPlot::showAllGraph()
{
    //每一个QCustomPlot都有上下左右4个坐标轴，分别为customPlot->xAxis2、xAxis、yAxis、yAxis2
    //每个轴可设置是否显示、是否显示刻度、几个刻度、刻度的值是否显示等
    //上下两个X轴可以设置不同的可视范围，不同的图层可以绑定其中一个X轴:
    //customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2)
    //addGraph默认是绑定下X轴、左Y轴。
    this->xAxis->rescale(true);
    this->yAxis->rescale(true);

    this->replot();
}

void MyCustomPlot::keyPressEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Escape) {
        rbCancel = true;
        rbRect->hide();
    }

    QCustomPlot::keyPressEvent(e);
}

void MyCustomPlot::mousePressEvent(QMouseEvent *event)
{
    if(QApplication::keyboardModifiers() == Qt::ShiftModifier && (event->buttons() & Qt::LeftButton)) {
        rbStartPos = event->pos();
        rbCancel = false;
        rbRect->resize(0, 0);
        rbRect->show();
    }
    else {
        QCustomPlot::mousePressEvent(event);
    }
}

bool MyCustomPlot::eventFilter(QObject *watched, QEvent *event)
{
    return QCustomPlot::eventFilter(watched, event);
}

void MyCustomPlot::mouseMoveEvent(QMouseEvent *event)
{
    /*
     * 鼠标按下时记录一次坐标，释放时再记录一次坐标，这两个点构成的矩形就作为选区，如果是从左上向右下进行框选这没毛病，
     * 如果从右下向左上进行框选，右下点和左上点，这两个点不符合QRec的构造函数形参要求;
     * 直接用来设置rb->setGeometry(rect);就会显示不出来，因为setGeometry的本质形参是(x,y,w,h)，
     * 右下点和左上点相减得出的宽度w和高度h都是负的，左下和右上点得出的w+y-等等，只有左上和右下才能得出w+y+。
     * 可以自行判断两个点的位置，并重新构造一个合理的x、y、w、h，但是没必要费这个劲，QRect::normalized()就是做这个事情的
     *
     * button()返回“发生了此事件的按钮”，buttons()返回"发生事件时还处于按下状态的按钮"
     */
    if(QApplication::keyboardModifiers() == Qt::ShiftModifier && (event->buttons() & Qt::LeftButton)) {
        QRect curRect = QRect(rbStartPos, event->pos()).normalized();
        rbRect->setGeometry(curRect);
    }
    else {
        QCustomPlot::mouseMoveEvent(event);
    }
}

void MyCustomPlot::mouseReleaseEvent(QMouseEvent *event)
{
    /*
     * QWidget像素坐标转换为曲线的XY轴坐标: xAxis->pixelToCoord(xx)，
     *                     反向功能函数为 xAxis->coordTopixel(xx)
     */
    if(event->modifiers() == Qt::ShiftModifier && event->button() == Qt::LeftButton) {
        rbRect->hide();
        if(!rbCancel) {
            QRect endRect = QRect(rbStartPos, event->pos()).normalized();
            rbRect->setGeometry(endRect);
            this->xAxis->setRange(this->xAxis->pixelToCoord(endRect.left()),
                                  this->xAxis->pixelToCoord(endRect.right()));
            this->yAxis->setRange(this->yAxis->pixelToCoord(endRect.bottom()),
                                  this->yAxis->pixelToCoord(endRect.top()));
            this->replot();

            rbCancel = true;
        }
        //qDebug() << "rectZoom";
    }
    else {
        QCustomPlot::mouseReleaseEvent(event);
    }
}

void MyCustomPlot::ClrFireData()
{
    for(int i = 0; i < FIREDATALEN; i++) {
        fireData[i].clear();
    }
}

void MyCustomPlot::SaveFireData(uint8_t index, double data)
{
    if(index < FIREDATALEN) {
        fireData[index].append(data);
    }
}

void MyCustomPlot::showFireGraph()
{
    int sz;

    for(int i = 0; i < FIREDATALEN; i++) {
        sz = fireData[i].size();
        if(sz > 0) {
            QVector<double> vSZ(sz);
            for(int j = 0; j < sz; j++) vSZ[j] = j;


        }
    }
}
